import { inherits as inherits$0 } from "util";
'use strict';
const inherits = { inherits: inherits$0 }.inherits;
function Reporter(options) {
    this._reporterState = {
        obj: null,
        path: [],
        options: options || {},
        errors: []
    };
}
Reporter.prototype.isError = function isError(obj) {
    return obj instanceof ReporterError;
};
Reporter.prototype.save = function save() {
    const state = this._reporterState;
    return { obj: state.obj, pathLen: state.path.length };
};
Reporter.prototype.restore = function restore(data) {
    const state = this._reporterState;
    state.obj = data.obj;
    state.path = state.path.slice(0, data.pathLen);
};
Reporter.prototype.enterKey = function enterKey(key) {
    return this._reporterState.path.push(key);
};
Reporter.prototype.exitKey = function exitKey(index) {
    const state = this._reporterState;
    state.path = state.path.slice(0, index - 1);
};
Reporter.prototype.leaveKey = function leaveKey(index, key, value) {
    const state = this._reporterState;
    this.exitKey(index);
    if (state.obj !== null)
        state.obj[key] = value;
};
Reporter.prototype.path = function path() {
    return this._reporterState.path.join('/');
};
Reporter.prototype.enterObject = function enterObject() {
    const state = this._reporterState;
    const prev = state.obj;
    state.obj = {};
    return prev;
};
Reporter.prototype.leaveObject = function leaveObject(prev) {
    const state = this._reporterState;
    const now = state.obj;
    state.obj = prev;
    return now;
};
Reporter.prototype.error = function error(msg) {
    let err;
    const state = this._reporterState;
    const inherited = msg instanceof ReporterError;
    if (inherited) {
        err = msg;
    }
    else {
        err = new ReporterError(state.path.map(function (elem) {
            return '[' + JSON.stringify(elem) + ']';
        }).join(''), msg.message || msg, msg.stack);
    }
    if (!state.options.partial)
        throw err;
    if (!inherited)
        state.errors.push(err);
    return err;
};
Reporter.prototype.wrapResult = function wrapResult(result) {
    const state = this._reporterState;
    if (!state.options.partial)
        return result;
    return {
        result: this.isError(result) ? null : result,
        errors: state.errors
    };
};
function ReporterError(path, msg) {
    this.path = path;
    this.rethrow(msg);
}
inherits(ReporterError, Error);
ReporterError.prototype.rethrow = function rethrow(msg) {
    this.message = msg + ' at: ' + (this.path || '(shallow)');
    if (Error.captureStackTrace)
        Error.captureStackTrace(this, ReporterError);
    if (!this.stack) {
        try {
            // IE only adds stack when thrown
            throw new Error(this.message);
        }
        catch (e) {
            this.stack = e.stack;
        }
    }
    return this;
};
export { Reporter };
